package cn.iocoder.yudao.framework.redis.core;

import cn.iocoder.yudao.framework.common.util.cache.CacheManager;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import org.redisson.api.*;

import java.time.Duration;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class RedisCacheManager implements CacheManager {

    private final RedissonClient redissonClient;

    public RedisCacheManager(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }


    public String get(String key) {
        RBucket<String> bucket = redissonClient.getBucket(key);
        return bucket.get();
    }

    public <T> T get(String key, Class<T> clazz) {
        RBucket<String> bucket = redissonClient.getBucket(key);
        return JsonUtils.parseObject(bucket.get(), clazz);
    }

    public <T> List<T> getList(String key, Class<T> clazz) {
        RBucket<String> bucket = redissonClient.getBucket(key);
        return JsonUtils.parseArray(bucket.get(), clazz);
    }


    public boolean set(String key, Object o) {
        RBucket<String> bucket = redissonClient.getBucket(key);
        bucket.set(JsonUtils.toJsonString(o));
        return true;
    }


    public boolean set(String key, long expire, Object o) {
        RBucket<String> bucket = redissonClient.getBucket(key);
        bucket.set(JsonUtils.toJsonString(o), expire, TimeUnit.SECONDS);
        return true;
    }


    public boolean delete(String key) {
        RBucket<Object> bucket = redissonClient.getBucket(key);
        return bucket.delete();
    }


    public boolean touch(String key, long expire) {
        RBucket<Object> bucket = redissonClient.getBucket(key);
        return bucket.expire(Duration.ofSeconds(expire));
    }


    public Long addCount(String key, long count, long expireTime) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        atomicLong.expire(Duration.ofSeconds(expireTime));
        return atomicLong.addAndGet(count);
    }


    public void clear() {
        redissonClient.getKeys().flushdb();
    }


    //批量获取匹配的所有的key
    public Set<String> getScan(String key, Integer count) {
        RKeys keys = redissonClient.getKeys();
        Iterable<String> keysByPattern = keys.getKeysByPattern(key, count);
        Set<String> r = new HashSet<>();
        for (String s : keysByPattern) {
            r.add(s);
        }
        return r;
    }

    //根据key模糊删除
    public boolean delLargeHashKey(String key) {
        RKeys keys = redissonClient.getKeys();
        keys.deleteByPattern(key);
        return true;
    }

    public void hSet(String key, String filedId, Object value) {
        if (value == null) {
            return;
        }
        redissonClient.getMap(key).put(filedId, value);
    }

    public <T> T hGet(String key, String filedId, Class<T> clazz) {
        RMap<String, T> map = redissonClient.getMap(key);
        return map.get(filedId);
    }

    public void sAdd(String key, String... values) {
        RSet<String> set = redissonClient.getSet(key);
        set.addAll(Arrays.asList(values));
    }

    public void sDel(String key, String... values) {
        RSet<String> set = redissonClient.getSet(key);
        set.removeAllAsync(Arrays.asList(values));
    }

    public Set<String> sListAll(String key) {
        RSet<String> set = redissonClient.getSet(key);
        return set.readAll();
    }

    public boolean sIfExits(String key, String value) {
        RSet<String> set = redissonClient.getSet(key);
        return set.contains(value);
    }

    public void setExpire(String key, long expire) {
        redissonClient.getBucket(key).expire(Duration.ofSeconds(expire));
    }
}
